package util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import sharedGameLogic.players.Character;
import view.impl.CharacterInfo;


public class CharacterLoader {
	
	private static int nbChars;
	private static Map<Integer, CharacterInfo> characterMap;
	private static List<sharedGameLogic.players.Character> modelCharacters = new LinkedList<Character>();
	
	private static CharacterLoadException exc = null;
	
	static {
		File charFolder = null;
		try {
			charFolder = new File(ResLoc.getResource("CharSelect.charFolder"));
		} catch (FileNotFoundException e) {
			exc = new CharacterLoadException("Unable to get characters folder.", e);
		}
		String[] characters = charFolder.list(new FilenameFilter() {
				
				@Override
				public boolean accept(File dir, String name) {	// Exclude hidden folders.
					if(name.startsWith("."))
						return false;
					return true;
				}
			});
		
		nbChars = characters.length;
		
		characterMap = new TreeMap<Integer, CharacterInfo>();
		
		int order = 0;
		for(String name : characters) {
			CharacterInfo c = new CharacterInfo();
			String directory = "";
			try {
				directory = ResLoc.getResource("CharSelect.charFolder") + "/" + name;
			} catch (FileNotFoundException e) {
				exc = new CharacterLoadException("Unable to get character folder.", e);
			} 
			
			c.setName(name);
			c.setCharImage(directory + "/image.png");
			c.setCharChosen(directory + "/chosen.png");
			c.setCharSelected(directory + "/selected.png");
			c.setOrder(order++);								//Change to better method. i.e: read from file.
			
			characterMap.put(c.getOrder(), c);
		}
		
		try {
			loadModelCharacters();
		} catch (CharacterLoadException e) {
			exc = e;
		}
	}
	
	private static void loadModelCharacters() throws CharacterLoadException {
		List<Integer> keys = new ArrayList<Integer>(characterMap.keySet());
		for(int i = 0; i < keys.size(); i++) {
			String charName = characterMap.get(keys.get(i)).getName();
			File charInfoFile;
			try {
				charInfoFile = new File(ResLoc.getResource("CharSelect.charFolder") + "/" + charName + "/info.xml" );
			} catch (FileNotFoundException e) {
				throw new CharacterLoadException("Unable to get character info file.", e);
			}
		
			DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuilder;
			try {
				docBuilder = docBuilderFactory.newDocumentBuilder();
			} catch (ParserConfigurationException e) {
				throw new CharacterLoadException(e);
			}
			
			Document doc;
			try {
				doc = docBuilder.parse(charInfoFile);
			} catch (SAXException e) {
				throw new CharacterLoadException(e);
			} catch (IOException e) {
				throw new CharacterLoadException(e);
			}
			
			String name;
			int strength;
			int agility;
			int skill;
			int reflex;
			int wisdom;
			int intelligence;
			int endurance;
			
			doc.getDocumentElement().normalize();
			
			name = doc.getDocumentElement().getAttribute("name");
			
			// Load the attributes.
			Element e;
			
			// STRENGHT
			e = (Element)(doc.getElementsByTagName("strength").item(0));
			strength = Integer.parseInt(e.getAttribute("amount").trim());
			
			// AGILITY
			e = (Element)(doc.getElementsByTagName("agility").item(0));
			agility = Integer.parseInt(e.getAttribute("amount").trim());
			
			// SKILL
			e = (Element)(doc.getElementsByTagName("skill").item(0));
			skill = Integer.parseInt(e.getAttribute("amount").trim());

			// REFLEX
			e = (Element)(doc.getElementsByTagName("reflex").item(0));
			reflex = Integer.parseInt(e.getAttribute("amount").trim());
			
			// WISDOM
			e = (Element)(doc.getElementsByTagName("wisdom").item(0));
			wisdom = Integer.parseInt(e.getAttribute("amount").trim());
			
			// INTELLIGENCE
			e = (Element)(doc.getElementsByTagName("intelligence").item(0));
			intelligence = Integer.parseInt(e.getAttribute("amount").trim());
			
			// ENDURANCE
			e = (Element)(doc.getElementsByTagName("endurance").item(0));
			endurance = Integer.parseInt(e.getAttribute("amount").trim());
			
			modelCharacters.add(new Character(name, strength, agility, skill, reflex, wisdom, intelligence, endurance));
		}
	}
	
	public static List<sharedGameLogic.players.Character> getModelCharacters() throws CharacterLoadException {
		if(exc == null) {
			return modelCharacters;
		} else {
			throw exc;
		}
	}
	
	public static int getNumberCharacters() throws CharacterLoadException {
		if(exc == null) {
			return nbChars;
		} else {
			throw exc;
		}
	}
	
	public static Map<Integer, CharacterInfo> getCharacterMap() throws CharacterLoadException {
		if(exc == null) {
			return characterMap;
		} else {
			throw exc;
		}
	}
}
